#coding=utf-8
#
# Copyright (C) 2014  NianNian TECH Co., Ltd. All rights reserved.
# Created on Jul 25, 2014, by Junn
#
from core.managers import BaseManager
from django.utils import timezone
from django.db.models import F
import datetime
from django.db.models.query_utils import Q

class RegardManager(BaseManager):
     
    def get_sent(self, user, last_time, limit_count=10):
        '''获取用户发送的问候列表'''
        if not last_time:
            return self.filter(author=user).order_by('-sent_time')[:limit_count]
        return self.filter(author=user, created_time__lte=last_time).order_by('-sent_time')[:limit_count]
     
    def get_received(self, user , last_time, limit_count=10, sender=None):
        '''获取用户收到的问候列表. 若sender不空, 则表示只返回该发送者发出的问候'''
         
        result_set = self.filter(receiver=user, status='S')
        if sender:
            result_set = result_set.filter(author__id=sender)
         
        if last_time:
            result_set = result_set.filter(sent_time__lte=last_time)
     
        return result_set.order_by('-sent_time')[:limit_count]
     
    def get_send_waitlist(self):
        '''取出已到发送时间的所有问候, 放入待发送列表waitlist'''
        return self.filter(is_sent_now=False, status='C', sent_time__lte=timezone.now())  #问候发送时间小于等于当前时间
     
    def count_new_received(self, user):
        '''统计用户新收到的问候数量'''
        return self.filter(receiver=user, status='S', sent_time__lte=timezone.now()).count()
     
    def set_to_sent(self, user): 
        '''当接收用户在客户端看到新问候时, 将问候状态设置为已发送'''
        self.filter(receiver=user, status='C', sent_time__lte=timezone.now()).update(status='S')
         
    def set_many_to_sent(self, regards):
        '''同时修改多个问候状态为已发送, 将保存到DB
        @param regards:  a QuerySet object . 用这个是否一定会优先执行?
        '''
        #regard_ids = [regard.id for regard in regards]
        #self.filter(id__in=regard_ids).update(status='S')
        regards.update(status='S')
            

class RegardMessageManager(BaseManager):
    
    def clear_message_count(self, receiver_id=None, msg_type='R', sender_id=None):     
        '''用户查看推送的问候消息后, 将消息计数清0
        @param receiver_di:消息推送的接收者. 若空, 则表示为系统消息, 该消息推送给了所有用户
        @param sender_id: 消息发送者. 若不为空, 则仅将该发送者发送给receiver_id的已推送消息清0 
        @param msg_type: 消息类型, 默认为'R'-问候消息, 'S'-系统消息, 'T'-提醒消息
        
        '''
        if not receiver_id and msg_type == 'S': #系统消息计数清0
            self.filter(sender=sender_id, msg_type='S', count__gt=0).update(count=0)
        
        qs = self.filter(receiver=receiver_id, count__gt=0, msg_type=msg_type)
        if not qs:
            return
        
        if sender_id:
            qs.filter(sender=sender_id, is_pushed=True).update(count=0)
        else:
            qs.update(count=0)   #用户刷新消息界面, 将消息计数清0. 使得消息无需再推送
            
            
    def get_many(self, user , last_time=None, limit_count=10):
        '''获取用户收到的消息列表(包括最新和历史消息), 
        @param last_time: 为分页参数, 为空时返回最新的10条.
        @param limit_count:返回多少条, 默认10 
        '''
        
        msgs = self.filter(receiver=user.id) | self.filter(msg_type='S')
        if not msgs:
            return []
        if last_time:
            return msgs.filter(item_time__lt=last_time).order_by('-item_time')[:limit_count]
        return msgs.order_by('-item_time')[:limit_count]
    
    def count_new(self, user):
        '''统计用户收到的新消息总数, 无论是否已被推送'''
        msgs = self.filter(receiver=user.id) | self.filter(msg_type='S')
        count = 0
        for msg in msgs:
            if msg.count > 0:
                count += msg.count
        return count        
    
    def set_pushed(self, user):
        '''将新消息读数清0, 同时将推送错误计数清0'''
        self.filter(receiver=user.id, count__gt=0, is_pushed=False).update(is_pushed=True, pushed_err_count=0)
    
class DateTipManager(BaseManager):
    
    def get_datetip_waitlist(self):
        '''返回需要触发的提醒事件, 这些提醒已到触发时间'''
        
        #F()表达式不可用, F无timedelta days属性. 改为原生SQL
        #return self.filter(spec_date__date=datetime.date.today() + datetime.timedelta(F('notice_type')), is_triggered=False)
        
        ## spec_date日期与当前日期差若等于notice_type, 提前2分钟或超过8分钟以内都可以提醒, 
        ## 时间比较的部分可考虑放到访问TodayDateTip时 
        sql = '''select * from regards_datetip where 
                    to_days(current_date)+notice_type = to_days(spec_date) and 
                    hour(spec_date)=hour(now()) and 
                    (minute(now())-minute(spec_date)>=-2 and minute(now())-minute(spec_date) <= 3)'''  
        
        sql_where=['to_days(current_date)+notice_type = to_days(spec_date)', 
               'hour(spec_date)=hour(now())', 
               '(minute(now())-minute(spec_date)>=-2 and minute(now())-minute(spec_date) <= 8)']
        
        return self.filter(is_triggered=False).extra(where=sql_where)  #don't use raw, it's can'r return the QuerySet object
    
    def get_by_user(self, user, last_time=None, limit_count=10):
        '''返回用户的提醒列表. 
        已触发且未读的提醒排在前面, 其他数据按spec_date排序.  
        已触发且未读的提醒数据(简记为: TT)排在最前面, 其他提醒数据(简记为: OT).
        接口首次请求时, 返回数据中将包括所有 TT + OT(10条);
        仅OT参与分页.  当请求下一页时, 仅返回10条OT.  
        '''
        tips = self.filter(creator=user)
        
        # 无分页. 首次请求, 返回 所有已触发且未读的提醒数据 + 10条其他提醒数据 
        if not last_time:    
            t_tips = tips.filter(is_triggered=True, is_checked=False)       #已触发且未读的提醒
            o_tips = tips.exclude(is_triggered=True, is_checked=False).order_by('spec_date')[:limit_count]      #其他提醒
            #print len(o_tips), o_tips.query
            #print len(t_tips), t_tips.query
            return t_tips | o_tips
        
        # 带分页. 仅返回10条其他数据
        return tips.exclude(is_triggered=True, is_checked=False).filter(spec_date__gt=last_time).order_by('spec_date')[:limit_count]      #其他提醒
        
            
class SystemMsgManager(BaseManager):
    
    def get_received(self, user=None, last_time=None, limit_count=10):
        '''用户收到的系统通知及消息'''
       
        msgs = self.filter(type='S1', is_checked=False)
        if user:
            msgs = msgs | self.filter(receiver=user)
        
        if last_time:
            return msgs.filter(item_time__lte=last_time).order_by('-created_time')[:limit_count]
        return msgs.order_by('-created_time')[:limit_count]          
        

        